home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gstype42.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  24.9 KB  |  862 lines

  1. /* Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gstype42.c,v 1.7.2.2 2000/11/09 21:32:30 rayjj Exp $ */
  20. /* Type 42 (TrueType) font library routines */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsstruct.h"
  25. #include "gsccode.h"
  26. #include "gsline.h"        /* for gs_imager_setflat */
  27. #include "gsmatrix.h"
  28. #include "gsutil.h"
  29. #include "gxchrout.h"
  30. #include "gxfixed.h"        /* for gxpath.h */
  31. #include "gxpath.h"
  32. #include "gxfont.h"
  33. #include "gxfont42.h"
  34. #include "gxistate.h"
  35.  
  36. /* Structure descriptor */
  37. public_st_gs_font_type42();
  38.  
  39. /* Forward references */
  40. private int append_outline(P4(uint glyph_index, const gs_matrix_fixed * pmat,
  41.                   gx_path * ppath, gs_font_type42 * pfont));
  42. private int default_get_outline(P3(gs_font_type42 *pfont, uint glyph_index,
  43.                    gs_const_string *pgstr));
  44. private int default_get_metrics(P4(gs_font_type42 *pfont, uint glyph_index,
  45.                    int wmode, float sbw[4]));
  46.  
  47. /* Set up a pointer to a substring of the font data. */
  48. /* Free variables: pfont, string_proc. */
  49. #define ACCESS(base, length, vptr)\
  50.   BEGIN\
  51.     code = (*string_proc)(pfont, (ulong)(base), length, &vptr);\
  52.     if ( code < 0 ) return code;\
  53.   END
  54.  
  55. /* Get 2- or 4-byte quantities from a table. */
  56. #define U8(p) ((uint)((p)[0]))
  57. #define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
  58. #define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
  59. #define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
  60. #define u32(p) get_u32_msb(p)
  61.  
  62. /* ---------------- Font level ---------------- */
  63.  
  64. /* Initialize the cached values in a Type 42 font. */
  65. /* Note that this initializes get_outline and the font procedures as well. */
  66. int
  67. gs_type42_font_init(gs_font_type42 * pfont)
  68. {
  69.     int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
  70.     pfont->data.string_proc;
  71.     const byte *OffsetTable;
  72.     uint numTables;
  73.     const byte *TableDirectory;
  74.     uint i;
  75.     int code;
  76.     byte head_box[8];
  77.     ulong loca_size = 0;
  78.  
  79.     ACCESS(0, 12, OffsetTable);
  80.     {
  81.     static const byte version1_0[4] = {0, 1, 0, 0};
  82.     static const byte version_true[4] = {'t', 'r', 'u', 'e'};
  83.  
  84.     if (memcmp(OffsetTable, version1_0, 4) &&
  85.         memcmp(OffsetTable, version_true, 4))
  86.         return_error(gs_error_invalidfont);
  87.     }
  88.     numTables = U16(OffsetTable + 4);
  89.     ACCESS(12, numTables * 16, TableDirectory);
  90.     /* Clear optional entries. */
  91.     memset(pfont->data.metrics, 0, sizeof(pfont->data.metrics));
  92.     for (i = 0; i < numTables; ++i) {
  93.     const byte *tab = TableDirectory + i * 16;
  94.     ulong offset = u32(tab + 8);
  95.  
  96.     if (!memcmp(tab, "glyf", 4))
  97.         pfont->data.glyf = offset;
  98.     else if (!memcmp(tab, "head", 4)) {
  99.         const byte *head;
  100.  
  101.         ACCESS(offset, 54, head);
  102.         pfont->data.unitsPerEm = U16(head + 18);
  103.         memcpy(head_box, head + 36, 8);
  104.         pfont->data.indexToLocFormat = U16(head + 50);
  105.     } else if (!memcmp(tab, "hhea", 4)) {
  106.         const byte *hhea;
  107.  
  108.         ACCESS(offset, 36, hhea);
  109.         pfont->data.metrics[0].numMetrics = U16(hhea + 34);
  110.     } else if (!memcmp(tab, "hmtx", 4)) {
  111.         pfont->data.metrics[0].offset = offset;
  112.         pfont->data.metrics[0].length = (uint)u32(tab + 12);
  113.     } else if (!memcmp(tab, "loca", 4)) {
  114.         pfont->data.loca = offset;
  115.         loca_size = u32(tab + 12);
  116.     } else if (!memcmp(tab, "vhea", 4)) {
  117.         const byte *vhea;
  118.  
  119.         ACCESS(offset, 36, vhea);
  120.         pfont->data.metrics[1].numMetrics = U16(vhea + 34);
  121.     } else if (!memcmp(tab, "vmtx", 4)) {
  122.         pfont->data.metrics[1].offset = offset;
  123.         pfont->data.metrics[1].length = (uint)u32(tab + 12);
  124.     }
  125.     }
  126.     loca_size >>= pfont->data.indexToLocFormat + 1;
  127.     pfont->data.numGlyphs = (loca_size == 0 ? 0 : loca_size - 1);
  128.     /*
  129.      * If the font doesn't have a valid FontBBox, compute one from the
  130.      * 'head' information.  Since the Adobe PostScript driver sometimes
  131.      * outputs garbage FontBBox values, we use a "reasonableness" check
  132.      * here.
  133.      */
  134.     if (pfont->FontBBox.p.x >= pfont->FontBBox.q.x ||
  135.     pfont->FontBBox.p.y >= pfont->FontBBox.q.y ||
  136.     pfont->FontBBox.p.x < -0.5 || pfont->FontBBox.p.x > 0.5 ||
  137.     pfont->FontBBox.p.y < -0.5 || pfont->FontBBox.p.y > 0.5
  138.     ) {
  139.     float upem = pfont->data.unitsPerEm;
  140.  
  141.     pfont->FontBBox.p.x = S16(head_box) / upem;
  142.     pfont->FontBBox.p.y = S16(head_box + 2) / upem;
  143.     pfont->FontBBox.q.x = S16(head_box + 4) / upem;
  144.     pfont->FontBBox.q.y = S16(head_box + 6) / upem;
  145.     }
  146.     pfont->data.get_outline = default_get_outline;
  147.     pfont->data.get_metrics = default_get_metrics;
  148.     pfont->procs.glyph_outline = gs_type42_glyph_outline;
  149.     pfont->procs.glyph_info = gs_type42_glyph_info;
  150.     pfont->procs.enumerate_glyph = gs_type42_enumerate_glyph;
  151.     return 0;
  152. }
  153.  
  154. /* ---------------- Glyph level ---------------- */
  155.  
  156. /* Define the bits in the component glyph flags. */
  157. #define cg_argsAreWords 1
  158. #define cg_argsAreXYValues 2
  159. #define cg_roundXYToGrid 4
  160. #define cg_haveScale 8
  161. #define cg_moreComponents 32
  162. #define cg_haveXYScale 64
  163. #define cg_have2x2 128
  164. #define cg_useMyMetrics 512
  165.  
  166. /*
  167.  * Parse the definition of one component of a composite glyph.  We don't
  168.  * bother to parse the component index, since the caller can do this so
  169.  * easily.
  170.  */
  171. private void
  172. parse_component(const byte **pdata, uint *pflags, gs_matrix_fixed *psmat,
  173.         int *pmp /*[2], may be null*/, const gs_font_type42 *pfont,
  174.         const gs_matrix_fixed *pmat)
  175. {
  176.     const byte *gdata = *pdata;
  177.     uint flags;
  178.     double factor = 1.0 / pfont->data.unitsPerEm;
  179.     gs_matrix_fixed mat;
  180.     gs_matrix scale_mat;
  181.  
  182.     flags = U16(gdata);
  183.     gdata += 4;
  184.     mat = *pmat;
  185.     if (flags & cg_argsAreXYValues) {
  186.     int arg1, arg2;
  187.     gs_fixed_point pt;
  188.  
  189.     if (flags & cg_argsAreWords)
  190.         arg1 = S16(gdata), arg2 = S16(gdata + 2), gdata += 4;
  191.     else
  192.         arg1 = S8(gdata), arg2 = S8(gdata + 1), gdata += 2;
  193.     if (flags & cg_roundXYToGrid) {
  194.         /* We should do something here, but we don't. */
  195.     }
  196.     gs_point_transform2fixed(pmat, arg1 * factor,
  197.                  arg2 * factor, &pt);
  198.     /****** HACK: WE KNOW ABOUT FIXED MATRICES ******/
  199.     mat.tx = fixed2float(mat.tx_fixed = pt.x);
  200.     mat.ty = fixed2float(mat.ty_fixed = pt.y);
  201.     if (pmp)
  202.         pmp[0] = pmp[1] = -1;
  203.     } else {
  204.     if (flags & cg_argsAreWords) {
  205.         if (pmp)
  206.         pmp[0] = U16(gdata), pmp[1] = S16(gdata + 2);
  207.         gdata += 4;
  208.     } else {
  209.         if (pmp)
  210.         pmp[0] = U8(gdata), pmp[1] = U8(gdata + 1);
  211.         gdata += 2;
  212.     }
  213.     }
  214. #define S2_14(p) (S16(p) / 16384.0)
  215.     if (flags & cg_haveScale) {
  216.     scale_mat.xx = scale_mat.yy = S2_14(gdata);
  217.     scale_mat.xy = scale_mat.yx = 0;
  218.     gdata += 2;
  219.     } else if (flags & cg_haveXYScale) {
  220.     scale_mat.xx = S2_14(gdata);
  221.     scale_mat.yy = S2_14(gdata + 2);
  222.     scale_mat.xy = scale_mat.yx = 0;
  223.     gdata += 4;
  224.     } else if (flags & cg_have2x2) {
  225.     scale_mat.xx = S2_14(gdata);
  226.     scale_mat.xy = S2_14(gdata + 2);
  227.     scale_mat.yx = S2_14(gdata + 4);
  228.     scale_mat.yy = S2_14(gdata + 6);
  229.     gdata += 8;
  230.     } else
  231.     goto no_scale;
  232. #undef S2_14
  233.     scale_mat.tx = 0;
  234.     scale_mat.ty = 0;
  235.     /* The scale doesn't affect mat.t{x,y}, so we don't */
  236.     /* need to update the fixed components. */
  237.     gs_matrix_multiply(&scale_mat, (const gs_matrix *)&mat,
  238.                (gs_matrix *)&mat);
  239. no_scale:
  240.     *pdata = gdata;
  241.     *pflags = flags;
  242.     *psmat = mat;
  243. }
  244.  
  245. /* Compute the total number of points in a (possibly composite) glyph. */
  246. private int
  247. total_points(gs_font_type42 *pfont, uint glyph_index)
  248. {
  249.     gs_const_string glyph_string;
  250.     int code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
  251.     const byte *gdata = glyph_string.data;
  252.  
  253.     if (code < 0)
  254.     return code;
  255.     if (glyph_string.size == 0)
  256.     return 0;
  257.     if (S16(gdata) != -1) {
  258.     /* This is a simple glyph. */
  259.     int numContours = S16(gdata);
  260.     const byte *pends = gdata + 10;
  261.     const byte *pinstr = pends + numContours * 2;
  262.  
  263.     return (numContours == 0 ? 0 : U16(pinstr - 2) + 1);
  264.     }
  265.     /* This is a composite glyph.  Add up the components. */
  266.     gdata += 10;
  267.     {
  268.     uint flags;
  269.     gs_matrix_fixed mat;
  270.     int total = 0;
  271.  
  272.     memset(&mat, 0, sizeof(mat)); /* arbitrary */
  273.     do {
  274.         code = total_points(pfont, U16(gdata + 2));
  275.         if (code < 0)
  276.         return code;
  277.         total += code;
  278.         parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
  279.     }
  280.     while (flags & cg_moreComponents);
  281.     return total;
  282.     }
  283. }
  284.  
  285. /* Define the default implementation for getting the outline data for */
  286. /* a glyph, using indexToLocFormat and the loca and glyf tables. */
  287. /* Set pglyph->data = 0 if the glyph is empty. */
  288. private int
  289. default_get_outline(gs_font_type42 * pfont, uint glyph_index,
  290.             gs_const_string * pglyph)
  291. {
  292.     int (*string_proc) (P4(gs_font_type42 *, ulong, uint, const byte **)) =
  293.     pfont->data.string_proc;
  294.     const byte *ploca;
  295.     ulong glyph_start;
  296.     uint glyph_length;
  297.     int code;
  298.  
  299.     /*
  300.      * We can't assume that consecutive loca entries are stored
  301.      * contiguously in memory: we have to access each entry
  302.      * individually.
  303.      */
  304.     if (pfont->data.indexToLocFormat) {
  305.     ACCESS(pfont->data.loca + glyph_index * 4, 4, ploca);
  306.     glyph_start = u32(ploca);
  307.     ACCESS(pfont->data.loca + glyph_index * 4 + 4, 4, ploca);
  308.     glyph_length = u32(ploca) - glyph_start;
  309.     } else {
  310.     ACCESS(pfont->data.loca + glyph_index * 2, 2, ploca);
  311.     glyph_start = (ulong) U16(ploca) << 1;
  312.     ACCESS(pfont->data.loca + glyph_index * 2 + 2, 2, ploca);
  313.     glyph_length = ((ulong) U16(ploca) << 1) - glyph_start;
  314.     }
  315.     pglyph->size = glyph_length;
  316.     if (glyph_length == 0)
  317.     pglyph->data = 0;
  318.     else
  319.     ACCESS(pfont->data.glyf + glyph_start, glyph_length, pglyph->data);
  320.     return 0;
  321. }
  322.  
  323. /* Parse a glyph into pieces, if any. */
  324. private int
  325. parse_pieces(gs_font_type42 *pfont, gs_glyph glyph, gs_glyph *pieces,
  326.          int *pnum_pieces)
  327. {
  328.     uint glyph_index = glyph - gs_min_cid_glyph;
  329.     gs_const_string glyph_string;
  330.     int code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
  331.  
  332.     if (code < 0)
  333.     return code;
  334.     if (glyph_string.size != 0 && S16(glyph_string.data) == -1) {
  335.     /* This is a composite glyph. */
  336.     int i = 0;
  337.     uint flags = cg_moreComponents;
  338.     const byte *gdata = glyph_string.data + 10;
  339.     gs_matrix_fixed mat;
  340.  
  341.     memset(&mat, 0, sizeof(mat)); /* arbitrary */
  342.     for (i = 0; flags & cg_moreComponents; ++i) {
  343.         if (pieces)
  344.         pieces[i] = U16(gdata + 2) + gs_min_cid_glyph;
  345.         parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
  346.     }
  347.     *pnum_pieces = i;
  348.     } else
  349.     *pnum_pieces = 0;
  350.     return 0;
  351. }
  352.  
  353. /* Define the font procedures for a Type 42 font. */
  354. int
  355. gs_type42_glyph_outline(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
  356.             gx_path *ppath)
  357. {
  358.     gs_font_type42 *const pfont = (gs_font_type42 *)font;
  359.     uint glyph_index = glyph - gs_min_cid_glyph;
  360.     gs_fixed_point origin;
  361.     int code;
  362.     gs_glyph_info_t info;
  363.     gs_matrix_fixed fmat;
  364.     static const gs_matrix imat = { identity_matrix_body };
  365.  
  366.     if (pmat == 0)
  367.     pmat = &imat;
  368.     if ((code = gs_matrix_fixed_from_matrix(&fmat, pmat)) < 0 ||
  369.     (code = gx_path_current_point(ppath, &origin)) < 0 ||
  370.     (code = append_outline(glyph_index, &fmat, ppath, pfont)) < 0 ||
  371.     (code = font->procs.glyph_info(font, glyph, pmat,
  372.                        GLYPH_INFO_WIDTH, &info)) < 0
  373.     )
  374.     return code;
  375.     return gx_path_add_point(ppath, origin.x + float2fixed(info.width[0].x),
  376.                  origin.y + float2fixed(info.width[0].y));
  377. }
  378. int
  379. gs_type42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
  380.              int members, gs_glyph_info_t *info)
  381. {
  382.     gs_font_type42 *const pfont = (gs_font_type42 *)font;
  383.     uint glyph_index = glyph - gs_min_cid_glyph;
  384.     int default_members =
  385.     members & ~(GLYPH_INFO_WIDTHS | GLYPH_INFO_NUM_PIECES |
  386.             GLYPH_INFO_PIECES);
  387.     gs_const_string outline;
  388.     int code = 0;
  389.  
  390.     if (default_members) {
  391.     code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
  392.  
  393.     if (code < 0)
  394.         return code;
  395.     } else if ((code = pfont->data.get_outline(pfont, glyph_index, &outline)) < 0)
  396.     return code;        /* non-existent glyph */
  397.     else
  398.     info->members = 0;
  399.     if (members & GLYPH_INFO_WIDTH) {
  400.     int i;
  401.  
  402.     for (i = 0; i < 2; ++i)
  403.         if (members & (GLYPH_INFO_WIDTH0 << i)) {
  404.         float sbw[4];
  405.  
  406.         code = gs_type42_wmode_metrics(pfont, glyph_index, i, sbw);
  407.         if (code < 0)
  408.             return code;
  409.         if (pmat)
  410.             code = gs_point_transform(sbw[2], sbw[3], pmat,
  411.                           &info->width[i]);
  412.         else
  413.             info->width[i].x = sbw[2], info->width[i].y = sbw[3];
  414.         }
  415.     info->members |= members & GLYPH_INFO_WIDTH;
  416.     }
  417.     if (members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES)) {
  418.     gs_glyph *pieces =
  419.         (members & GLYPH_INFO_PIECES ? info->pieces : (gs_glyph *)0);
  420.     int code = parse_pieces(pfont, glyph, pieces, &info->num_pieces);
  421.  
  422.     if (code < 0)
  423.         return code;
  424.     info->members |= members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
  425.     }
  426.     return code;
  427. }
  428. int
  429. gs_type42_enumerate_glyph(gs_font *font, int *pindex,
  430.               gs_glyph_space_t glyph_space, gs_glyph *pglyph)
  431. {
  432.     gs_font_type42 *const pfont = (gs_font_type42 *)font;
  433.  
  434.     while (++*pindex <= pfont->data.numGlyphs) {
  435.     gs_const_string outline;
  436.     uint glyph_index = *pindex - 1;
  437.     int code = pfont->data.get_outline(pfont, glyph_index, &outline);
  438.  
  439.     if (code < 0)
  440.         return code;
  441.     if (outline.data == 0)
  442.         continue;        /* empty (undefined) glyph */
  443.     *pglyph = glyph_index + gs_min_cid_glyph;
  444.     return 0;
  445.     }
  446.     /* We are done. */
  447.     *pindex = 0;
  448.     return 0;
  449. }
  450.  
  451. /* Get the metrics of a simple glyph. */
  452. private int
  453. simple_glyph_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
  454.              float sbw[4])
  455. {
  456.     int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
  457.     pfont->data.string_proc;
  458.     double factor = 1.0 / pfont->data.unitsPerEm;
  459.     uint width;
  460.     int lsb;
  461.     int code;
  462.  
  463.     {
  464.     const gs_type42_mtx_t *pmtx = &pfont->data.metrics[wmode];
  465.     uint num_metrics = pmtx->numMetrics;
  466.     const byte *pmetrics;
  467.  
  468.     if (glyph_index < num_metrics) {
  469.         ACCESS(pmtx->offset + glyph_index * 4, 4, pmetrics);
  470.         width = U16(pmetrics);
  471.         lsb = S16(pmetrics + 2);
  472.     } else {
  473.         uint offset = pmtx->offset + num_metrics * 4;
  474.         uint glyph_offset = (glyph_index - num_metrics) * 2;
  475.         const byte *plsb;
  476.  
  477.         ACCESS(offset - 4, 4, pmetrics);
  478.         width = U16(pmetrics);
  479.         if (glyph_offset >= pmtx->length)
  480.         glyph_offset = pmtx->length - 2;
  481.         ACCESS(offset + glyph_offset, 2, plsb);
  482.         lsb = S16(plsb);
  483.     }
  484.     }
  485.     if (wmode) {
  486.     factor = -factor;    /* lsb and width go down the page */
  487.     sbw[0] = 0, sbw[1] = lsb * factor;
  488.     sbw[2] = 0, sbw[3] = width * factor;
  489.     } else {
  490.     sbw[0] = lsb * factor, sbw[1] = 0;
  491.     sbw[2] = width * factor, sbw[3] = 0;
  492.     }
  493.     return 0;
  494. }
  495.  
  496. /* Get the metrics of a glyph. */
  497. private int
  498. default_get_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
  499.             float sbw[4])
  500. {
  501.     gs_const_string glyph_string;
  502.     int code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
  503.  
  504.     if (code < 0)
  505.     return code;
  506.     if (glyph_string.size != 0 && S16(glyph_string.data) == -1) {
  507.     /* This is a composite glyph. */
  508.     uint flags;
  509.     const byte *gdata = glyph_string.data + 10;
  510.     gs_matrix_fixed mat;
  511.  
  512.     memset(&mat, 0, sizeof(mat)); /* arbitrary */
  513.     do {
  514.         uint comp_index = U16(gdata + 2);
  515.  
  516.         parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
  517.         if (flags & cg_useMyMetrics) {
  518.         return gs_type42_wmode_metrics(pfont, comp_index, wmode, sbw);
  519.         }
  520.     }
  521.     while (flags & cg_moreComponents);
  522.     }
  523.     return simple_glyph_metrics(pfont, glyph_index, wmode, sbw);
  524. }
  525. int
  526. gs_type42_wmode_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
  527.             float sbw[4])
  528. {
  529.     return pfont->data.get_metrics(pfont, glyph_index, wmode, sbw);
  530. }
  531. int
  532. gs_type42_get_metrics(gs_font_type42 * pfont, uint glyph_index,
  533.               float sbw[4])
  534. {
  535.     return gs_type42_wmode_metrics(pfont, glyph_index, pfont->WMode, sbw);
  536. }
  537.  
  538. /* Define the bits in the glyph flags. */
  539. #define gf_OnCurve 1
  540. #define gf_xShort 2
  541. #define gf_yShort 4
  542. #define gf_Repeat 8
  543. #define gf_xPos 16        /* xShort */
  544. #define gf_xSame 16        /* !xShort */
  545. #define gf_yPos 32        /* yShort */
  546. #define gf_ySame 32        /* !yShort */
  547.  
  548. /* Append a TrueType outline to a path. */
  549. /* Note that this does not append the final moveto for the width. */
  550. int
  551. gs_type42_append(uint glyph_index, gs_imager_state * pis,
  552.          gx_path * ppath, const gs_log2_scale_point * pscale,
  553.          bool charpath_flag, int paint_type, gs_font_type42 * pfont)
  554. {
  555.     int code = append_outline(glyph_index, &pis->ctm, ppath, pfont);
  556.  
  557.     if (code < 0)
  558.     return code;
  559.     /* Set the flatness for curve rendering. */
  560.     return gs_imager_setflat(pis, gs_char_flatness(pis, 1.0));
  561. }
  562.  
  563. /*
  564.  * Append a simple glyph outline to a path (ppath != 0) and/or return
  565.  * its list of points (ppts != 0).
  566.  */
  567. private int
  568. append_simple(const byte *gdata, float sbw[4], const gs_matrix_fixed *pmat,
  569.           gx_path *ppath, gs_fixed_point *ppts, gs_font_type42 * pfont)
  570. {
  571.     int numContours = S16(gdata);
  572.     const byte *pends = gdata + 10;
  573.     const byte *pinstr = pends + numContours * 2;
  574.     const byte *pflags;
  575.     uint npoints;
  576.     const byte *pxc, *pyc;
  577.     int code;
  578.  
  579.     if (numContours == 0)
  580.     return 0;
  581.     /*
  582.      * It appears that the only way to find the X and Y coordinate
  583.      * tables is to parse the flags.  If this is true, it is an
  584.      * incredible piece of bad design.
  585.      */
  586.     {
  587.     const byte *pf = pflags = pinstr + 2 + U16(pinstr);
  588.     uint xbytes = npoints = U16(pinstr - 2) + 1;
  589.     uint np = npoints;
  590.  
  591.     while (np > 0) {
  592.         byte flags = *pf++;
  593.         uint reps = (flags & gf_Repeat ? *pf++ + 1 : 1);
  594.  
  595.         if (!(flags & gf_xShort)) {
  596.         if (flags & gf_xSame)
  597.             xbytes -= reps;
  598.         else
  599.             xbytes += reps;
  600.         }
  601.         np -= reps;
  602.     }
  603.     pxc = pf;
  604.     pyc = pxc + xbytes;
  605.     }
  606.  
  607.     /* Interpret the contours. */
  608.  
  609.     {
  610.     uint i, np;
  611.     gs_fixed_point pt;
  612.     double factor = 1.0 / pfont->data.unitsPerEm;
  613.     /*
  614.      * Decode the first flag byte outside the loop, to avoid a
  615.      * compiler warning about uninitialized variables.
  616.      */
  617.     byte flags = *pflags++;
  618.     uint reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
  619.  
  620.     /*
  621.      * The TrueType documentation gives no clue as to how the lsb
  622.      * should affect placement of the outline.  Our best guess is
  623.      * that the outline should be translated by lsb - xMin.
  624.      */
  625.     gs_point_transform2fixed(pmat, sbw[0] - S16(gdata + 2) * factor,
  626.                  0.0, &pt);
  627.     for (i = 0, np = 0; i < numContours; ++i) {
  628.         bool move = true;
  629.         uint last_point = U16(pends + i * 2);
  630.         float dx, dy;
  631.         int off_curve = 0;
  632.         gs_fixed_point start;
  633.         gs_fixed_point cpoints[3];
  634.  
  635.         for (; np <= last_point; --reps, ++np) {
  636.         gs_fixed_point dpt;
  637.  
  638.         if (reps == 0) {
  639.             flags = *pflags++;
  640.             reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
  641.         }
  642.         if (flags & gf_xShort) {
  643.             /*
  644.              * A bug in the Watcom compiler prevents us from doing
  645.              * the following with the obvious conditional expression.
  646.              */
  647.             if (flags & gf_xPos)
  648.             dx = *pxc++ * factor;
  649.             else
  650.             dx = -(int)*pxc++ * factor;
  651.         } else if (!(flags & gf_xSame))
  652.             dx = S16(pxc) * factor, pxc += 2;
  653.         else
  654.             dx = 0;
  655.         if (flags & gf_yShort) {
  656.             /* See above under dx. */
  657.             if (flags & gf_yPos)
  658.             dy = *pyc++ * factor;
  659.             else
  660.             dy = -(int)*pyc++ * factor;
  661.         } else if (!(flags & gf_ySame))
  662.             dy = S16(pyc) * factor, pyc += 2;
  663.         else
  664.             dy = 0;
  665.         code = gs_distance_transform2fixed(pmat, dx, dy, &dpt);
  666.         if (code < 0)
  667.             return code;
  668.         pt.x += dpt.x, pt.y += dpt.y;
  669.         if (ppts)    /* return the points */
  670.             ppts[np] = pt;
  671.         if (ppath) {    /* append to a path */
  672. #define control1(xy) cpoints[1].xy
  673. #define control2(xy) cpoints[2].xy
  674. #define control3off(xy) ((cpoints[1].xy + pt.xy) / 2)
  675. #define control4off(xy) ((cpoints[0].xy + 2 * cpoints[1].xy) / 3)
  676. #define control5off(xy) ((2 * cpoints[1].xy + cpoints[2].xy) / 3)
  677. #define control6off(xy) ((2 * cpoints[1].xy + pt.xy) / 3)
  678. #define control7off(xy) ((2 * cpoints[1].xy + start.xy) / 3)
  679.             if (move) {
  680.             if_debug2('1', "[1t]start (%g,%g)\n",
  681.                   fixed2float(pt.x), fixed2float(pt.y));
  682.             start = pt;
  683.             code = gx_path_add_point(ppath, pt.x, pt.y);
  684.             cpoints[0] = pt;
  685.             move = false;
  686.             } else if (flags & gf_OnCurve) {
  687.             if_debug2('1', "[1t]ON (%g,%g)\n",
  688.                   fixed2float(pt.x), fixed2float(pt.y));
  689.             if (off_curve)
  690.                 code = gx_path_add_curve(ppath, control4off(x),
  691.                         control4off(y), control6off(x),
  692.                         control6off(y), pt.x, pt.y);
  693.             else
  694.                 code = gx_path_add_line(ppath, pt.x, pt.y);
  695.             cpoints[0] = pt;
  696.             off_curve = 0;
  697.             } else {
  698.             if_debug2('1', "[1t]...off (%g,%g)\n",
  699.                   fixed2float(pt.x), fixed2float(pt.y));
  700.             switch (off_curve++) {
  701.             default:    /* >= 1 */
  702.                 control2(x) = control3off(x);
  703.                 control2(y) = control3off(y);
  704.                 code = gx_path_add_curve(ppath,
  705.                         control4off(x), control4off(y),
  706.                         control5off(x), control5off(y),
  707.                         control2(x), control2(y));
  708.                 cpoints[0] = cpoints[2];
  709.                 off_curve = 1;
  710.                 /* falls through */
  711.             case 0:
  712.                 cpoints[1] = pt;
  713.             }
  714.             }
  715.             if (code < 0)
  716.             return code;
  717.         }
  718.         }
  719.         if (ppath) {
  720.         if (off_curve)
  721.             code = gx_path_add_curve(ppath,
  722.                     control4off(x), control4off(y),
  723.                     control7off(x), control7off(y),
  724.                     start.x, start.y);
  725.         code = gx_path_close_subpath(ppath);
  726.         if (code < 0)
  727.             return code;
  728.         }
  729.     }
  730.     }
  731.     return 0;
  732. }
  733.  
  734. /* Append a glyph outline. */
  735. private int
  736. check_component(uint glyph_index, const gs_matrix_fixed *pmat,
  737.         gx_path *ppath, gs_font_type42 *pfont, gs_fixed_point *ppts,
  738.         const byte **pgdata)
  739. {
  740.     gs_const_string glyph_string;
  741.     const byte *gdata;
  742.     float sbw[4];
  743.     int numContours;
  744.     int code;
  745.  
  746.     code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
  747.     if (code < 0)
  748.     return code;
  749.     gdata = glyph_string.data;
  750.     if (gdata == 0 || glyph_string.size == 0)    /* empty glyph */
  751.     return 0;
  752.     numContours = S16(gdata);
  753.     if (numContours >= 0) {
  754.     simple_glyph_metrics(pfont, glyph_index, pfont->WMode, sbw);
  755.     code = append_simple(gdata, sbw, pmat, ppath, ppts, pfont);
  756.     return (code < 0 ? code : 0); /* simple */
  757.     }
  758.     if (numContours != -1)
  759.     return_error(gs_error_rangecheck);
  760.     *pgdata = gdata;
  761.     return 1;            /* composite */
  762. }
  763. private int
  764. append_component(uint glyph_index, const gs_matrix_fixed * pmat,
  765.          gx_path * ppath, gs_fixed_point *ppts, int point_index,
  766.          gs_font_type42 * pfont)
  767. {
  768.     const byte *gdata;
  769.     int code;
  770.  
  771.     code = check_component(glyph_index, pmat, ppath, pfont, ppts + point_index,
  772.                &gdata);
  773.     if (code != 1)
  774.     return code;
  775.     /*
  776.      * This is a composite glyph.  Because of the "point matching" feature,
  777.      * we have to do an extra pass over each component to fill in the
  778.      * table of points.
  779.      */
  780.     {
  781.     uint flags;
  782.  
  783.     gdata += 10;
  784.     do {
  785.         uint comp_index = U16(gdata + 2);
  786.         gs_matrix_fixed mat;
  787.         int mp[2];
  788.  
  789.         parse_component(&gdata, &flags, &mat, mp, pfont, pmat);
  790.         if (mp[0] >= 0) {
  791.         /* Match up points.  What a nuisance! */
  792.         const gs_fixed_point *const pfrom = ppts + mp[0];
  793.         /*
  794.          * Contrary to the TrueType documentation, mp[1] is not
  795.          * relative to the start of the compound glyph, but is
  796.          * relative to the start of the component.
  797.          */
  798.         const gs_fixed_point *const pto = ppts + point_index + mp[1];
  799.         gs_fixed_point diff;
  800.  
  801.         code = append_component(comp_index, &mat, NULL, ppts,
  802.                     point_index, pfont);
  803.         if (code < 0)
  804.             return code;
  805.         diff.x = pfrom->x - pto->x;
  806.         diff.y = pfrom->y - pto->y;
  807.         mat.tx = fixed2float(mat.tx_fixed += diff.x);
  808.         mat.ty = fixed2float(mat.ty_fixed += diff.y);
  809.         }
  810.         code = append_component(comp_index, &mat, ppath, ppts,
  811.                     point_index, pfont);
  812.         if (code < 0)
  813.         return code;
  814.         point_index += total_points(pfont, comp_index);
  815.     }
  816.     while (flags & cg_moreComponents);
  817.     }
  818.     return 0;
  819. }
  820. private int
  821. append_outline(uint glyph_index, const gs_matrix_fixed * pmat,
  822.            gx_path * ppath, gs_font_type42 * pfont)
  823. {
  824.     {
  825.     const byte *gdata;
  826.     int code =
  827.         check_component(glyph_index, pmat, ppath, pfont, NULL, &gdata);
  828.  
  829.     if (code != 1)
  830.         return code;
  831.     }
  832.     {
  833.     /*
  834.      * Set up the points array (only needed for point matching, sigh).
  835.      * We use stack allocation if possible, to avoid creating a sandbar
  836.      * (pts will be allocated before, but also freed before, any path
  837.      * elements).
  838.      */
  839. #define MAX_STACK_PTS 150    /* usually enough */
  840.     int num_points = total_points(pfont, glyph_index);
  841.  
  842.     if (num_points <= MAX_STACK_PTS) {
  843.         gs_fixed_point pts[MAX_STACK_PTS];
  844.  
  845.         return append_component(glyph_index, pmat, ppath, pts, 0, pfont);
  846.     } else {
  847.         gs_memory_t *mem = pfont->memory; /* any memory will do */
  848.         gs_fixed_point *ppts = (gs_fixed_point *)
  849.         gs_alloc_byte_array(mem, num_points, sizeof(gs_fixed_point),
  850.                     "append_outline");
  851.         int code;
  852.  
  853.         if (ppts == 0)
  854.         return_error(gs_error_VMerror);
  855.         code = append_component(glyph_index, pmat, ppath, ppts, 0, pfont);
  856.         gs_free_object(mem, ppts, "append_outline");
  857.         return code;
  858.     }
  859. #undef MAX_STACK_PTS
  860.     }
  861. }
  862.